package postgres

import (
	"auth/model"
	"auth/model/entity"
	"proto/dto"
	"strconv"
)

var User = &user{}

type user struct{}

func (a *user) Create(m *entity.User) (int64, error) {
	err := db.Create(m).Error
	return m.ID, err
}

func (a *user) Find(id int64) (*entity.User, error) {
	e := &entity.User{}
	err := db.Model(&entity.User{}).First(&e, id).Error
	return e, err
}

func (a *user) Update(id int64, dict map[string]interface{}) error {
	return db.Model(&entity.User{}).Where("id = ?", id).Updates(dict).Error
}

func (a *user) Delete(id int64) error {
	return db.Delete(&entity.User{}, id).Error
}

// AllUserIds 获取所有用户id
func (a *user) AllUserIds() (ids []int64, err error) {
	err = db.Model(&entity.User{}).Pluck("id", &ids).Error
	return
}

func (a *user) List(in *model.UserListRequest) (int64, []*entity.User, error) {
	var (
		q     = db.Model(&entity.User{})
		err   error
		total int64
		users = make([]*entity.User, 0)
	)

	if in.UserId > 0 {
		q = q.Where("id::text like ?", "%"+strconv.Itoa(int(in.UserId))+"%")
	}

	if in.Name != "" {
		q = q.Where("name like ?", "%"+in.Name+"%")
	}

	if in.Phone != "" {
		q = q.Where("phone like ?", "%"+in.Phone+"%")
	}

	if in.Status != nil {
		q = q.Where("status = ?", *in.Status)
	}

	if in.StartTime > 0 {
		q = q.Where("created_at > ?", in.StartTime)
	}

	if in.EndTime > 0 {
		q = q.Where("created_at < ?", in.EndTime)
	}

	q = q.Where("type in (?)", model.UserTypes)

	if err = q.Count(&total).Error; err != nil {
		return 0, users, err
	}

	if err = q.Limit(in.Size).Offset((in.Index - 1) * in.Size).Order("updated_at desc").Find(&users).Error; err != nil {
		return 0, users, err
	}

	return total, users, nil
}

func (a *user) GetSysUserList(in *model.GetSysUserListRequest, deptIds []int64) (int64, []*model.GetSysUserList, error) {
	var (
		q     = db.Model(&entity.User{})
		err   error
		total int64
		users = make([]*model.GetSysUserList, 0)
	)
	q = q.Where("type in (?)", model.SysUserTypes)
	if in.DeptId > 0 {
		q = q.Where(" dept_id IN (?)", deptIds)
	}
	if err = q.Count(&total).Error; err != nil {
		return total, users, err
	}
	if err = q.Select("users.*,(select dept_name from depts where users.dept_id=depts.dept_id ) as dept_name ").
		Limit(in.Size).
		Offset((in.Index - 1) * in.Size).
		Order("updated_at desc").Find(&users).Error; err != nil {
		return total, users, err
	}
	return total, users, err
}

func (a *user) FindByParameter(in *model.UserInfo) (*entity.User, error) {
	var (
		err    error
		q      = db.Model(&entity.User{})
		entity entity.User
	)
	if in.ID != 0 {
		q = q.Where("id = ?", in.ID)
	}
	if in.WxID != "" {
		q = q.Where("wx_id = ?", in.WxID)
	}
	if in.Phone != "" {
		q = q.Where("phone = ?", in.Phone)
	}
	if in.AppleID != "" {
		q = q.Where("apple_id = ?", in.AppleID)
	}
	if in.Name != "" {
		q = q.Where("name = ?", in.Name)
	}
	if in.Type != "" {
		q = q.Where("type = ?", in.Type)
	}
	if in.Status >= 0 {
		q = q.Where("status = ?", in.Status)
	}

	err = q.First(&entity).Error
	return &entity, err
}

func (a *user) CheckDeptExistUser(deptId int64) (int64, error) {
	var (
		q     = db.Debug().Model(&entity.User{})
		count int64
		err   error
	)
	err = q.Where("dept_id =?", deptId).Count(&count).Limit(1).Error
	return count, err
}

func (a *user) FindUserByPhone(phone string) (entity.User, error) {
	var (
		loginUser entity.User
	)
	// 逻辑删除的用户排除
	err := db.Model(&entity.User{}).Where("phone=?", phone).First(&loginUser).Error
	return loginUser, err
}

// Count 用户统计
func (a *user) Count(user int64) (*model.UserCount, error) {
	var (
		//countEty model.UserCount
		q     = db.Debug().Model(&entity.User{})
		count int64
		err   error
	)
	err = q.Where("type in (?)", model.UserTypes).Count(&count).Error

	return nil, err
}

func (a *user) UserListByIds(in dto.UserListInfoRequest) (out dto.UserListInfoResponse, err error) {
	var (
		q       = db.Model(&entity.User{})
		outList = make([]*dto.UserInfoResponse, 0)
		etys    = make([]*entity.User, 0)
	)
	err = q.Where("id in ?", in.Ids).Find(&etys).Error
	if err != nil {
		return out, err
	}

	for _, ety := range etys {
		outList = append(outList, &dto.UserInfoResponse{
			Id:      ety.ID,
			Phone:   ety.Phone,
			Name:    ety.Name,
			Picture: ety.Picture,
			Status:  int32(ety.Status),
		})
	}

	out.List = outList
	return out, err
}
